#include "pcode.h"

struct pcode* constrPcode()
{
	struct pcode *ret=malloc(sizeof( struct pcode));

	ret->size=0;
	ret->capaciteMax=INIT_CAPACITE_PCODE;

	ret->codes=malloc(INIT_CAPACITE_PCODE*sizeof(struct instruction *));
	return ret;
}

void addOperation(struct pcode *p, char CodeOp[3], int Type, char sValue[256], char Commentaire[58])
{
	if(p->size<p->capaciteMax)
	{
		p->codes[p->size]=malloc(sizeof(struct instruction));
		
		strcpy(p->codes[p->size]->codeOp, CodeOp);
		strcpy(p->codes[p->size]->value, sValue);

		p->codes[p->size]->type=Type;

		strcpy(p->codes[p->size]->commentaire, Commentaire);

		p->size++;
	}
	else
	{
		int nouvelleTaille=p->capaciteMax*COEF_CODES;
		struct instruction **nouvelleBase=malloc(nouvelleTaille*sizeof(struct instruction *));
		
		memcpy(nouvelleBase, p->codes, (p->size)*sizeof(struct instruction *));
		free(p->codes);

		p->capaciteMax=nouvelleTaille;
		p->codes=nouvelleBase;

		p->codes[p->size]=malloc(sizeof(struct instruction));

		strcpy(p->codes[p->size]->codeOp, CodeOp);

		p->codes[p->size]->type=Type;

		strcpy(p->codes[p->size]->value, sValue);
		strcpy(p->codes[p->size]->commentaire, Commentaire);

		p->size++;
	}
}

void savePcode(struct pcode *src, FILE *dest)
{
	if(src!=NULL && src->size>0)
	{
		int i;
		char header[128];
		sprintf(header, "------------------------ P_CODE ------------------------\nNbInstruction=%d;\n", src->size);
		fputs(header, dest);

		for(i=0; i<src->size; ++i)
		{
			char buffer[80];

			if(src->codes[i]->type==t_string)
			{
				int j;
				for(j=0; j<strlen(src->codes[i]->value); ++j)
				{
					if(src->codes[i]->value[j]==' ') src->codes[i]->value[j]='$';
				}
			}
			sprintf(buffer, "%d %s %d, %s\n", i, src->codes[i]->codeOp, src->codes[i]->type, src->codes[i]->value);

			fputs(buffer, dest);
		}
	}
}

void nettoyerPcode(struct pcode *p)
{	
	if(p->size>0)
	{
		int i;

		for(i=0; i<p->size; ++i)
		{
			p->size--;
			free(p->codes[p->size]);
		}
	
		free(p->codes);
		p->capaciteMax=INIT_CAPACITE_PCODE;
		p->codes=NULL;
		p->size=0;
		p->codes=malloc(INIT_CAPACITE_PCODE*sizeof(struct instruction *));
	}
}

void affichagePcode(struct pcode *p)
{
	printf("Info pcode:\nTaille=%d\n\n", p->size);

	if(p->size>0)
	{
		int i;

		for(i=0; i<p->size; ++i)
		{
			char buffer[128];
			sprintf(buffer, "%d %s %d, %s %s", i, p->codes[i]->codeOp, p->codes[i]->type, p->codes[i]->value, p->codes[i]->commentaire); 
			printf("%s\n", buffer);
		}
	}
}

void loadPcode(struct liste *lst, struct pcode *dest, FILE *src)
{
	if(lst!=NULL && dest!=NULL && src!=NULL)
	{	
		if(dest->size>0)
			nettoyerPcode(dest);

		if(lst->nbElem>0)
			nettoyerListe(lst);

		char *line=malloc(256*sizeof(char));
		int nRead, totalLigne=0, j=0;

		getline(&line, &nRead, src);					/*Ligne header du fichier*/
		getline(&line, &nRead, src);					/*Nombre d'instruction p_code*/
		nRead=sscanf(line, "NbInstruction=%d;", &totalLigne); 
	
		while(j<totalLigne)						/*Récupération des instructions p_codes*/
		{
			int type, i, res, value;
			free(line);

			char *codeOp=malloc(3*sizeof(char)), *sValue=malloc(256*sizeof(char));
			line=malloc(80*sizeof(char));
			
			getline(&line, &nRead, src);
			sscanf(line, "%d %s %d, %s\n", &i, codeOp, &type, sValue);

			if(type==t_string)
			{
				int j;
				for(j=0; j<strlen(sValue); ++j)
					if(sValue[j]=='$') sValue[j]=' ';
			}

			addOperation(dest, codeOp, type, sValue, "##");
			j++;
			free(codeOp);
		}

		getline(&line, &nRead, src);					/*Ligne header de la table des symbôles*/			
		getline(&line, &nRead, src);					/*Lecture du nombre de symbôle*/
		nRead=sscanf(line, "NbSymbole=%d;", &totalLigne); 
		struct liste *tmp=constrListe();
		j=0;

		while(j<totalLigne)						/*Lecture de chaque symbôle*/
		{
			int type_1, type_2, i, res;
			free(line);

			char *nom=malloc(128*sizeof(char)), *valeur=malloc(10*sizeof(char)), *nomEmplacement=malloc(128*sizeof(char));
			line=malloc(80*sizeof(char));
			struct symbole *courant=malloc(sizeof(struct symbole));
			
			getline(&line, &nRead, src);
			sscanf(line, "%s %d %d %s %d %s %d %d %d\n", courant->nom, &courant->typeIdentificateur, &courant->typeLiteral, courant->valeur, &courant->emplacement, courant->nomEmplacement, &courant->deplacement, &courant->nParam, &courant->passage);


			ajouterSymbole(tmp, courant->nom, courant->typeIdentificateur, courant->typeLiteral, courant->valeur, courant->emplacement, courant->deplacement,  courant->nomEmplacement, courant->nParam, courant->passage);
			j++;
			free(nom);
			free(valeur);
			free(nomEmplacement);
		}

		ajouterListeSymbole(lst, tmp);

		free(line);
	}
}

void loadSymboleIntoListe(struct liste *src, struct pile *dest, char emplacement[128], struct pcode *p_code, int flag)
{
	if(src!=NULL && dest!=NULL)
	{
		struct symbole *courant=src->tete;
		int i=0;
	
		while(courant!=NULL)
		{
			courant->deplacement=-1;

			if(strcmp(courant->nomEmplacement, emplacement)==0)
			{	
				char val[5]; 
				sprintf(val, "%d", i);

				courant->deplacement=dest->deplacement;
				empiler(dest, courant->nom, courant->valeur, courant->typeIdentificateur, courant->typeLiteral, courant->nomEmplacement);
				if(flag==1)
				{
					char info[128];
					sprintf(info, " #Chargement table des symboles %s => pile: variable %s", val, courant->nom);
					addOperation(p_code, "INC", 0, val, info);
				}
			
			}
			
			courant=courant->suivant;
			i++;
		}

	}
}

/*main()
{
	struct pcode *p=constrPcode();
	FILE *f=fopen("code.p_code", "r");

	/*addOperation(p, "LOD", 1, -1, 8, "Deplacement entier en case 8 de la pile");
	addOperation(p, "OPR", 1, 1, 0, "Addition entier vs entier");
	addOperation(p, "STO", 1, -1, 0, "Affectation entier à la case 0 de la pile");
	
	load(p, f);
	affichagePcode(p);
}*/
